// 相当于vue的构造函数
function MVVM(options) {
    // 将配置对象保存到vm
    this.$options = options;
    // 将data对象保存到vm和变量data中
    var data = this._data = this.$options.data;
    // 保存vm到me
    var me = this;

    // 数据代理
    // 实现 vm.xxx -> vm._data.xxx
    // 遍历data中所有的属性 key是属性名
    Object.keys(data).forEach(function(key) {
        // 对指定的属性实现代理
        me._proxy(key);
    });
    // 对data中所有层次的属性通过数据劫持实现数据绑定
    observe(data, this);
    // 编译解析模板
    this.$compile = new Compile(options.el || document.body, this)
}

MVVM.prototype = {
    $watch: function(key, cb, options) {
        new Watcher(this, key, cb);
    },
    // 实现指定属性代理的方法
    _proxy: function(key) {
        var me = this;
        // 给vm添加指定属性 使用属性描述符
        Object.defineProperty(me, key, {
            // 不能重新定义
            configurable: false,
            // 可以枚举遍历
            enumerable: true,
            // vm.xxx是调用，获取属性值 代理读
            get: function proxyGetter() {
                return me._data[key];
            },
            // value被保存到data中对象的属性上 代理写
            set: function proxySetter(newVal) {
                me._data[key] = newVal;
            }
        });
    }
};